package com.yuyaogc.lowcode.engine.proxy;

import com.yuyaogc.lowcode.engine.entity.EntityClass;
import com.yuyaogc.lowcode.engine.exception.EngineException;
import com.yuyaogc.lowcode.engine.exception.EngineLogger;
import com.yuyaogc.lowcode.engine.plugin.activerecord.Db;
import com.yuyaogc.lowcode.engine.plugin.activerecord.Model;
import com.yuyaogc.lowcode.engine.util.ClassUtils;
import com.yuyaogc.lowcode.engine.util.JsonUtil;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import java.util.Objects;



public class ProxyInv extends MyInv {
    private static final EngineLogger log = EngineLogger.me(ProxyInv.class);


    public <T> T invoke2(EntityClass entityClass,Method method, Map<String, Object> inArgsValues) {
        Parameter[] params = method.getParameters();
        Object[] args = new Object[params.length];

        for (int i = 0; i < params.length; i++) {
            Parameter parameter = params[i];
            String argName = parameter.getName();
            Object arg = inArgsValues.get(argName);
            args[i] = arg;
            if (Objects.isNull(arg)) {
                continue;
            }

            try {
                String s = JsonUtil.objectToString(arg);
                args[i] = JsonUtil.read(s, parameter.getParameterizedType(), arg.getClass());
            } catch (Exception e) {

            }
        }
        return invoke(entityClass,method, args);
    }

    public <T> T invoke(EntityClass entityClass, Method method, Object... args) {
        Class<?> clazz = method.getDeclaringClass();
        Connection conn = Db.getConfig().getThreadLocalConnection();
        if (conn != null) {
            try {
                Object object = ClassUtils.newInstance(entityClass,clazz);
                if (clazz.isAssignableFrom(Model.class)) {
                }
                return (T) method.invoke(object, args);
            } catch (Exception e) {
                throw new EngineException(e);
            }
        }

        try {
            conn = Db.getConfig().getConnection();
            Db.getConfig().setThreadLocalConnection(conn);
            try {
                Object object = ClassUtils.newInstance(entityClass,clazz);
                if (clazz.isAssignableFrom(Model.class)) {
                }
                return (T) method.invoke(object, args);
            } catch (Exception e) {
                log.error("method invoke exception", e);
                throw new EngineException(e);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            Db.getConfig().removeThreadLocalConnection();
            if (conn != null) {
                try {
                    conn.close();
                } catch (Exception e) {
                    System.err.println(e.getMessage());
                }
            }
        }
    }
}
